package cn.shop.merchant.config;

import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.db.DBAppenderBase;

import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

/**
 * @author : 李一涵
 * @date : Created in 2021-11-12 15:02
 * @description :
 */
public class DBAppender extends DBAppenderBase<ILoggingEvent> {

    protected static final Method GET_GENERATED_KEYS_METHOD;
    /** 插入sql */
    protected String insertSQL;
    /** message 日志内容 */
    static final int USERNAME = 1;
    /** level_string */
    static final int OPERATE = 2;
    /** logger_name 全类名 */
    static final int DETAIL = 3;

    static {
        // PreparedStatement.getGeneratedKeys() method was added in JDK 1.4
        Method getGeneratedKeysMethod;
        try {
            // the
            getGeneratedKeysMethod = PreparedStatement.class.getMethod("getGeneratedKeys", (Class[]) null);
        } catch (Exception ex) {
            getGeneratedKeysMethod = null;
        }
        GET_GENERATED_KEYS_METHOD = getGeneratedKeysMethod;
    }

    @Override
    public void start() {
        // 将写好的sql语句赋值给insertSQL
        insertSQL = buildInsertSql();
        super.start();
    }

    /** 自己写新增sql语句 */
    private static String buildInsertSql() {
        return "INSERT INTO `operator_log`(`username`,`operate`,`detail`) " +
                "VALUES (?,?,?)";
    }

    @Override
    protected Method getGeneratedKeysMethod() {
        return GET_GENERATED_KEYS_METHOD;
    }

    @Override
    protected String getInsertSQL() {
        return insertSQL;
    }

    @Override
    protected void subAppend(ILoggingEvent eventObject, Connection connection, PreparedStatement statement) throws Throwable {
        bindLoggingEventWithInsertStatement(statement, eventObject);
        // This is expensive... should we do it every time?
        int updateCount = statement.executeUpdate();
        System.out.println(updateCount);
        if (updateCount != 1) {
            addWarn("Failed to insert loggingEvent");
        }
    }

    @Override
    protected void secondarySubAppend(ILoggingEvent iLoggingEvent, Connection connection, long l) throws Throwable {

    }


    /**
     * 主要修改的方法
     *
     */
    private void bindLoggingEventWithInsertStatement(PreparedStatement stmt, ILoggingEvent event) throws SQLException {
        // event.getFormattedMessage() 日志打印内容
        String message = event.getFormattedMessage();
        // 如果只想存储自己打印的日志，可以这样写日志：logger.info("- XXXX")
        // 判断日志消息首字母为 - 的日志，记录到数据库表
        if(message.startsWith("DB:")){
            Object[] args = event.getArgumentArray();
            String name = "";
            String operate = "";
            if (args != null && args.length > 0) {
                name = String.valueOf(args[0]);
                operate = String.valueOf(args[1]);
            }
            stmt.setString(USERNAME, name);
            // event.getLevel().toString() 日志级别
            stmt.setString(OPERATE, operate);
            // event.getLoggerName() 全类名
            stmt.setString(DETAIL, event.getFormattedMessage());
        }
    }
}
